﻿using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.SideChannels;
using System;
using System.Collections.Generic;

public enum EnvSettingType
{
    SET_PARAMETER = 1,
    HARD_RESET = 2,
    OTHER = 3
}

public class EnvironmentSettingChannel : SideChannel
{
    private EnvironmentController envCtrler;
    public EnvironmentSettingChannel(EnvironmentController envCtrler)
    {
        this.envCtrler = envCtrler;
        ChannelId = new Guid("621f0a70-4f87-11ea-a6bf-784f4387d1f8");
    }

    protected override void OnMessageReceived(IncomingMessage msg)
    {
        int envSettingTypeInt = msg.ReadInt32();
        // All the enum parsing here have no error handler, because we also using enum implementation on python side.
        if((int)EnvSettingType.SET_PARAMETER == envSettingTypeInt)
        {
            var key = msg.ReadString();
            if(key == null)
                Debug.LogError("[EnvironmentSettingChannel]: Missing parameter key(got null).");

            int envParaTypeInt = msg.ReadInt32();
            object value;
            if(envParaTypeInt == (int)EnvParaType.BOOL)
                value = msg.ReadBoolean();
            else if(envParaTypeInt == (int)EnvParaType.FLOAT)
                value = msg.ReadFloat32();
            else if(envParaTypeInt == (int)EnvParaType.INT)
                value = msg.ReadInt32();
            else if(envParaTypeInt == (int)EnvParaType.LIST_FLOAT)
                value = new List<float>(msg.ReadFloatList());
            else if(envParaTypeInt == (int)EnvParaType.RANDOM_NORMAL || envParaTypeInt == (int)EnvParaType.RANDOM_UNIFORM)
            {
                var li = new List<float>(msg.ReadFloatList());
                if(li.Count != 3)
                    Debug.LogError("[EnvironmentSettingChannel]: The random parameter's"+
                    " value should be 3 float number in list, but actually got "+li.Count.ToString()+".");
                value = li;
            }
            else
                value = null;

            EP ep = (EP)Enum.Parse(typeof(EP), key);
            envCtrler.epm.SetPara(ep, (EnvParaType)Enum.ToObject(typeof(EnvParaType), envParaTypeInt), value); 
            if(value == null)
                Debug.Log("[EnvironmentSettingChannel]: Environment parameter \""+key+"\" set failed, get null value.");
            else
                Debug.Log("[EnvironmentSettingChannel]: Environment parameter \""+key+"\" set.");
        }
        else if((int)EnvSettingType.HARD_RESET == envSettingTypeInt)
        {
            envCtrler.isHardReset = true;
            envCtrler.EnvironmentReset();
            //Debug.Log("[EnvironmentSettingChannel]: EnvironmentSettingType: HARDRESET(not implemented).");
        }
        else
        {
            Debug.Log("[EnvironmentSettingChannel]: EnvironmentSettingType: OTHER(not implemented).");
        }
    }
}